package com.summer.filesync.util;

import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ConcurrentHashMap;

/** 简单日志工具类 提供基础的日志记录功能 */
public class Logger {

  public enum LogLevel {
    DEBUG(0),
    INFO(1),
    WARN(2),
    ERROR(3);

    private final int level;

    LogLevel(int level) {
      this.level = level;
    }

    public int getLevel() {
      return level;
    }
  }

  private static final SimpleDateFormat DATE_FORMAT =
      new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
  private static final ConcurrentHashMap<String, Logger> loggers = new ConcurrentHashMap<>();
  private static LogLevel currentLevel = LogLevel.INFO;
  private static boolean writeToFile = false;
  private static String logFilePath = "logs/system.log";

  private final String className;

  private Logger(String className) {
    this.className = className;
  }

  /** 获取Logger实例 */
  public static Logger getLogger(Class<?> clazz) {
    String className = clazz.getSimpleName();
    return loggers.computeIfAbsent(className, Logger::new);
  }

  /** 获取Logger实例 */
  public static Logger getLogger(String name) {
    return loggers.computeIfAbsent(name, Logger::new);
  }

  /** 设置日志级别 */
  public static void setLevel(LogLevel level) {
    currentLevel = level;
  }

  /** 启用文件日志 */
  public static void enableFileLogging(String filePath) {
    logFilePath = filePath;
    writeToFile = true;

    // 确保日志目录存在
    try {
      FileUtils.createDirectories(StringUtils.getParentPath(filePath));
    } catch (IOException e) {
      System.err.println("Failed to create log directory: " + e.getMessage());
    }
  }

  /** 禁用文件日志 */
  public static void disableFileLogging() {
    writeToFile = false;
  }

  /** DEBUG级别日志 */
  public void debug(String message) {
    log(LogLevel.DEBUG, message, null);
  }

  /** INFO级别日志 */
  public void info(String message) {
    log(LogLevel.INFO, message, null);
  }

  /** WARN级别日志 */
  public void warn(String message) {
    log(LogLevel.WARN, message, null);
  }

  /** WARN级别日志（带异常） */
  public void warn(String message, Throwable throwable) {
    log(LogLevel.WARN, message, throwable);
  }

  /** ERROR级别日志 */
  public void error(String message) {
    log(LogLevel.ERROR, message, null);
  }

  /** ERROR级别日志（带异常） */
  public void error(String message, Throwable throwable) {
    log(LogLevel.ERROR, message, throwable);
  }

  /** 记录日志 */
  private void log(LogLevel level, String message, Throwable throwable) {
    if (level.getLevel() < currentLevel.getLevel()) {
      return;
    }

    String formattedMessage = formatMessage(level, message, throwable);

    // 输出到控制台
    if (level == LogLevel.ERROR) {
      System.err.println(formattedMessage);
    } else {
      System.out.println(formattedMessage);
    }

    // 写入文件
    if (writeToFile) {
      writeToFile(formattedMessage);
    }
  }

  /** 格式化日志消息 */
  private String formatMessage(LogLevel level, String message, Throwable throwable) {
    StringBuilder sb = new StringBuilder();

    // 时间戳
    sb.append(DATE_FORMAT.format(new Date()));
    sb.append(" ");

    // 线程名
    sb.append("[").append(Thread.currentThread().getName()).append("]");
    sb.append(" ");

    // 日志级别
    sb.append(level.name());
    sb.append(" ");

    // 类名
    sb.append(className);
    sb.append(" - ");

    // 消息
    sb.append(message);

    // 异常信息
    if (throwable != null) {
      sb.append("\n");
      sb.append(getStackTrace(throwable));
    }

    return sb.toString();
  }

  /** 获取异常堆栈信息 */
  private String getStackTrace(Throwable throwable) {
    StringWriter sw = new StringWriter();
    PrintWriter pw = new PrintWriter(sw);
    throwable.printStackTrace(pw);
    return sw.toString();
  }

  /** 写入日志文件 */
  private synchronized void writeToFile(String message) {
    try (FileWriter fw = new FileWriter(logFilePath, true);
        PrintWriter pw = new PrintWriter(fw)) {
      pw.println(message);
    } catch (IOException e) {
      System.err.println("Failed to write to log file: " + e.getMessage());
    }
  }

  /** 格式化当前时间 */
  public static String getCurrentTime() {
    return DATE_FORMAT.format(new Date());
  }
}
